#pragma once

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <optional>
#include <limits>
#include <algorithm>

// --- 基础数据结构 ---

struct CodeMap {
    int ALLOC = 0, FREE = 0;
    int L1 = 0, UB = 0, L0A = 0, L0B = 0, L0C = 0;
};

struct NodeData {
    int id = -1;
    std::string op;
    std::optional<int> buf_id;
    std::optional<long long> size;
    std::string type;
    std::string pipe;
    std::optional<int> cycles;
    std::vector<int> bufs;
    int op_code = 0;
    int type_code = 0;
};

struct Graph {
    std::vector<NodeData> nodes;
    std::vector<std::vector<int>> adj_list;
    std::vector<std::vector<int>> predecessors_list;
    int num_nodes = 0;
};

// *** MODIFIED: Removed default initializers ***
struct Caps {
    long long l1;
    long long ub;
    long long l0a;
    long long l0b;
    long long l0c;
};

// *** MODIFIED: Removed default initializers ***
struct Params {
    double min_farthest_use_threshold;
    double w_use;
    double w_vol;
    double w_vic;
    std::string alloc_strategy;
};

// *** MODIFIED: Removed default initializers ***
struct Options {
    int generations;
    int population_size;
    int batch_size;
    double schedule_move_prob;
    std::pair<double, double> threshold_range;
};

struct Solution {
    std::vector<int> final_schedule;
    std::unordered_map<int, long long> memory_offsets;
    std::unordered_map<int, long long> spill_map;
    long long total_spill_volume = 0;
    bool timed_out = false;
    bool spill_failed = false;
    double nodes_processed = 0;
};

struct Individual {
    std::vector<int> schedule;
    Params params;
    double time = std::numeric_limits<double>::infinity();
    double spill = std::numeric_limits<double>::infinity();

    int rank = 0;
    double crowding_distance = 0.0;
    int domination_count = 0;
    std::vector<int> dominated_solutions;

    Individual() = default;
    Individual(std::vector<int> sched, Params p, double t, double s)
        : schedule(std::move(sched)), params(std::move(p)), time(t), spill(s) {
    }
};

struct MemBlock {
    long long start;
    long long size;
    int buf_id; // -1 for free blocks

    bool operator<(const MemBlock& other) const {
        return start < other.start;
    }
};